Golang — context rewritten

Michalkowal
3 min readNov 4, 2022
Context as controller

The story will describe what context is, how you can use it and why you should use it. You are going to get useful knowledge about the subject, not the next big article about why you shouldn’t use it, or about some magic approaches regarding the context.

What is the context?

You can think of context as the one manager that controls all the employees. The manager doesn’t know much about the job but he can say to all the employees to stop, that's the context. Even more, the context can store key-value pairs of useful data that can be shared through your application.

The first example of your own context

This is the simplest context you can create in go. Basically it “catches” the context that is working in the background of a given part of the code. That it.

Then in the inner parts of the app, you can “listen” for the context being done, i.e. in some for loop with the select statement. Check the below example.

The code is rather simple. We are having Parent function which does 4 things:

  1. Creates context from background
  2. Creates waitGroup used to sync the main goroutine with the newly created one
  3. The execution of the Worker function in another goroutine

The Worker function basically works kind of in the “background” and waits for the signal from the context, that the job should be done. That all.

You are probably thinking about how we can send the Done signal through the context. There is nothing simpler, check out the example, it is just an expanded version of the previous one

As you can see, there is just a little change in the Parent function. We changed the default context into an extended version: context.WithCancel. This function returns the same context as above with one more function, the cancel. Cancel can be called in various places to signal the “done” state of the context. We are calling it in another goroutine after 500ms. It will then stop the execution of the Worker function.

The context in HTTP API

The context is the part of HTTP request in handler functions by the default

As you can see, you can use the r.Context() method to get current request context and pass it down into the rabbit hole. You can ask why? Well, the answer is kind of simple, let’s say that the fetchExistingPosts takes around 4s to execute. The caller of AddMediumPost isn’t patient and stops the request after 1s. There are 3s more of job which needs to be done for nothing. Here comes context, basically the cancel function is being called whenever the caller of the AddMediumPost ends too soon, and with that being said, all the work in the fetchExistingPosts can be done as well, and some resources can be spared on another job.

Handy tips

Almost always use context in functions/methods

With that being said, almost always use context as the first parameter of the function/method even if it isn’t needed there at the time. This rule applies to almost every longer than 20 lines function because there is a big chance that you are going to need the context there in the future, and trust me, adding it all over the calling functions tree is really long job. If you don’t need it at the moment, you can always declare it as the floor:

func SomeFunction(_ context.Context) error {}

Don’t pass it to struct fields

It sounds like a nice idea, to pass it to the struct and then reuse it in a lot of different methods without the need of repeating the first parameter context thingy. But that's wrong. You can use the same struct in a lot of different places using different contexts. Passing different contexts to the thing would be a really hard thing to do.

That's all

Thanks for reading. I wanted to pass some useful knowledge and tips to you to simplify your work around the golang code of yours. If you have any questions, ask in the comments, and I will answer those right away. See you next time!

--

--